package com.medical.system.filter;

import com.alibaba.fastjson.JSON;
import com.medical.system.common.Result;
import com.medical.system.common.ResultCodeEnum;
import com.medical.system.util.JwtHelper;
import com.medical.system.util.ResponseUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/***
 * @ 类的描述 :token身份验证过滤器，因为用户登录状态在token中存储在客户端，
 * 所以每次请求接口请求头携带token， 后台通过自定义token过滤器拦截解析token
 * 完成认证并填充用户信息实体。
 * @ 作者 : 风花雪月
 * @ 时间 : 2024/7/23 22:13
 * @ 参数 :
 * @return:
 **/
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    private RedisTemplate redisTemplate;

    public TokenAuthenticationFilter(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * @ 方法描述 :检验request中的身份验证
     * @ 作者 : 风花雪月
     * @ 时间 : 2024/7/24 15:44
     * @ 参数 : [request, response, filterChain]
     * @return: void
     **/
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        logger.info("uri:" + request.getRequestURI());
        //如果是登录接口，直接放行
        if ("/admin/system/index/login".equals(request.getRequestURI()) ||
                "/admin/system/upload/uploadImage".equals(request.getRequestURI()) ||
                "/admin/system/upload/uploadVideo".equals(request.getRequestURI())
        ) {
            filterChain.doFilter(request, response);
            return;
        }
//        如果身份验证不为空
        UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
        if (null != authentication) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
            filterChain.doFilter(request, response);
        } else {
//            为空，209：没有权限
            ResponseUtil.out(response, Result.build(null, ResultCodeEnum.PERMISSION));
        }
    }

    /**
     * @ 方法描述 :颁发token令牌，以及对应的权限授权
     * @ 作者 : 风花雪月
     * @ 时间 : 2024/7/24 15:45
     * @ 参数 : [request]
     * @return: org.springframework.security.authentication.UsernamePasswordAuthenticationToken
     **/
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        // token置于header里
        String token = request.getHeader("token");
        logger.info("token:" + token);
        if (!StringUtils.isEmpty(token)) {
            String useruame = JwtHelper.getUsername(token);
            logger.info("useruame:" + useruame);
            if (!StringUtils.isEmpty(useruame)) {
                String authoritiesString = (String) redisTemplate.opsForValue().get(useruame);
                List<Map> mapList = JSON.parseArray(authoritiesString, Map.class);
                List<SimpleGrantedAuthority> authorities = new ArrayList<>();
                for (Map map : mapList) {
                    authorities.add(new SimpleGrantedAuthority((String) map.get("authority")));
                }
                return new UsernamePasswordAuthenticationToken(useruame, null, authorities);
            }
        }
        return null;
    }
}
